/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import liquibase.sdk.Main;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.cache.DictCache;
import org.springblade.common.constant.MaintenanceSmsConstant;
import org.springblade.common.constant.TemplateMsgConstant;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseEntity;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.MaintainPlanAffairDTO;
import org.springblade.modules.admin.entity.*;
import org.springblade.modules.admin.enums.MaintainPlanContentEnum;
import org.springblade.modules.admin.enums.TaskStatusEnum;
import org.springblade.modules.admin.mapper.MaintainPlanContentMapper;
import org.springblade.modules.admin.service.*;
import org.springblade.modules.admin.vo.ElevatorVO;
import org.springblade.modules.admin.vo.MaintainPlanAffairVO;
import org.springblade.modules.admin.mapper.MaintainPlanAffairMapper;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.modules.admin.vo.MalFunctionHistoryVO;
import org.springblade.modules.admin.vo.PlanContentWorkDetailCommonVo;
import org.springblade.modules.admin.vo.plan.*;
import org.springblade.modules.admin.vo.user.UserAffairAndCheckVo;
import org.springblade.modules.resource.utils.SmsUtil;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springblade.modules.system.vo.SimpleUserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static org.springblade.modules.admin.service.BuildingService.PROJECT_TYPE_CODE;

/**
 * 事务工单表 服务实现类
 *
 * @author ysq
 * @since 2023-11-10
 */
@Service
@Slf4j
public class MaintainPlanAffairServiceImpl extends BaseServiceImpl<MaintainPlanAffairMapper, MaintainPlanAffair> implements IMaintainPlanAffairService {

	@Autowired
	private IMaintainPlanContentService maintainPlanContentService;

	@Autowired
	private MaintainPlanContentMapper maintainPlanContentMapper;


	@Autowired
	private IMaintainPlanContentExtService maintainPlanContentExtService;
	@Autowired
	private IMaintainPlanContentUserService maintainPlanContentUserService;
	@Autowired
	private IUserService userService;
	@Autowired
	private MaintainMalfunctionLogService malfunctionLogService;
	@Autowired
	private IMaintainSignService signService;

	@Autowired
	private ElevatorService elevatorService;

	@Autowired
	private IMaintainMalfunctionHistoryService malfunctionHistoryService;

	@Autowired
	@Lazy
	private WeChatDialogueService weChatDialogueService;

	@Autowired
	private IMaintainPlanRelationService maintainPlanRelationService;

	@Autowired
	private IMaintainPlanCheckService maintainPlanCheckService;

	@Autowired
	private IMaintainByScoreQuestionService maintainByScoreQuestionService;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Long add(MaintainPlanAffairVO maintainPlanAffair) {
		Long planId = null;
		String userName = AuthUtil.getNickName();
		String address = "";
		for (Long elevatorId : maintainPlanAffair.getElevatorIds()) {
			ElevatorVO elevatorVO = elevatorService.selectElevator(elevatorId);
			if (StrUtil.isEmpty(address)) {
				address = address + elevatorVO.getBuildingName() + "-" + elevatorVO.getElevatorAddress();
			} else {
				address = address + "," + elevatorVO.getBuildingName() + "-" + elevatorVO.getElevatorAddress();
			}
			//第一步保存工单
			MaintainPlanContent maintainPlanContent = new MaintainPlanContent();
			maintainPlanContent.setTypeStatus(MaintainPlanContentEnum.MAINTAIN_AFFAIR.getId());
			maintainPlanContent.setPlanDate(maintainPlanAffair.getPlanDate());
			maintainPlanContent.setElevatorId(elevatorId);
			maintainPlanContent.setStatus(maintainPlanAffair.getUserIds().size() > 0 ? TaskStatusEnum.SW_TO_START.getStatus() : TaskStatusEnum.SW_ALLOCATION.getStatus());
			maintainPlanContentService.save(maintainPlanContent);
			planId = maintainPlanContent.getId();
			//第二步初始化工单扩展表
			MaintainPlanContentExt maintainPlanContentExt = new MaintainPlanContentExt();
			maintainPlanContentExt.setPlanId(maintainPlanContent.getId());
			maintainPlanContentExtService.save(maintainPlanContentExt);
			//第三步事务信息
			MaintainPlanAffair maintainPlanAffair1 = new MaintainPlanAffairVO();
			BeanUtil.copyProperties(maintainPlanAffair, maintainPlanAffair1);
			maintainPlanAffair1.setPlanId(maintainPlanContent.getId());
			this.save(maintainPlanAffair1);

			//质检问题点关联工单
			if (maintainPlanAffair.getMalHistId() != null) {
				MaintainMalfunctionHistory maintainMalfunctionHistory = malfunctionHistoryService.getById(maintainPlanAffair.getMalHistId());
				maintainMalfunctionHistory.setChildPlanId(maintainPlanContent.getId());
				malfunctionHistoryService.updateById(maintainMalfunctionHistory);
				//保存关系
				MaintainPlanRelation maintainPlanRelation = new MaintainPlanRelation();
				maintainPlanRelation.setOwnPlanId(maintainPlanContent.getId());
				maintainPlanRelation.setFromPlanId(maintainPlanAffair.getCheckPlanId());
				maintainPlanRelationService.save(maintainPlanRelation);

				//更新质检工单的子工单数量
				MaintainPlanContent planContent = maintainPlanContentService.getById(maintainPlanAffair.getCheckPlanId());
				if (planContent.getTypeStatus() == MaintainPlanContentEnum.MAINTAIN_CHECK.getId()) {
					MaintainPlanCheck maintainPlanCheck = maintainPlanCheckService.getOne(Wrappers.<MaintainPlanCheck>lambdaQuery().eq(MaintainPlanCheck::getPlanId, maintainPlanAffair.getCheckPlanId()));
					Integer childCounts = Convert.toInt(maintainPlanCheck.getChildCounts(), 0);
					maintainPlanCheck.setChildCounts(childCounts + 1);
					maintainPlanCheckService.updateById(maintainPlanCheck);
				}
			} else if (StrUtil.isNotEmpty(maintainPlanAffair.getByQuestionIds())) {
				 List<MaintainByScoreQuestion> maintainByScoreQuestions = maintainByScoreQuestionService.listByIds(Arrays.asList(maintainPlanAffair.getByQuestionIds().split(",")));
				for (MaintainByScoreQuestion maintainByScoreQuestion : maintainByScoreQuestions) {
					maintainByScoreQuestion.setChildPlanId(maintainPlanContent.getId());
					maintainByScoreQuestion.setChildPlanCreateUserName(AuthUtil.getNickName());
					maintainByScoreQuestion.setChildPlanCreateUser(AuthUtil.getUserId());
					maintainByScoreQuestion.setChildPlanType(MaintainPlanContentEnum.MAINTAIN_AFFAIR.getId());
					maintainByScoreQuestionService.updateById(maintainByScoreQuestion);
				}
				//保存关系
				MaintainPlanRelation maintainPlanRelation = new MaintainPlanRelation();
				maintainPlanRelation.setOwnPlanId(maintainPlanContent.getId());
				maintainPlanRelation.setFromPlanId(maintainByScoreQuestions.get(0).getPlanId());
				maintainPlanRelationService.save(maintainPlanRelation);
			}

			//第四步分配人员
			for (Long userId : maintainPlanAffair.getUserIds()) {
				MaintainPlanContentUser maintainPlanContentUser = new MaintainPlanContentUser();
				maintainPlanContentUser.setUserId(userId);
				maintainPlanContentUser.setPlanId(maintainPlanContent.getId());

				PlanUserSignDetailVo planUserSignDetailVo = new PlanUserSignDetailVo();
				planUserSignDetailVo.setUserName(userService.getById(userId).getRealName());
				planUserSignDetailVo.setPlanId(maintainPlanContent.getId());
				maintainPlanContentUser.setSignInfo(JSON.toJSONString(planUserSignDetailVo));

				maintainPlanContentUserService.save(maintainPlanContentUser);
			}
			//第六步 增加每个工单的日志追踪
			MaintainMalfunctionLog maintainMalfunctionLog = new MaintainMalfunctionLog();
			maintainMalfunctionLog.setPlanStatus(TaskStatusEnum.SW_ALLOCATION.getStatus());
			maintainMalfunctionLog.setPlanId(maintainPlanContent.getId());
			maintainMalfunctionLog.setExecutor(userName);
			maintainMalfunctionLog.setTypeName("创建工单");
			malfunctionLogService.save(maintainMalfunctionLog);

			if (maintainPlanAffair.getUserIds().size() > 0) {
				List<String> userNames = userService.listByIds(maintainPlanAffair.getUserIds()).stream().map(User::getRealName).distinct().collect(Collectors.toList());
				MaintainMalfunctionLog maintainMalfunctionLog2 = new MaintainMalfunctionLog();
				maintainMalfunctionLog2.setPlanId(maintainPlanContent.getId());
				maintainMalfunctionLog2.setPlanStatus(TaskStatusEnum.SW_TO_START.getStatus());
				maintainMalfunctionLog2.setExecutor(userName);
				maintainMalfunctionLog2.setTypeName("分配人员[" + String.join("/", userNames) + "]");
				maintainMalfunctionLog2.setUserNames(String.join("/", userNames));
				malfunctionLogService.save(maintainMalfunctionLog2);
			}
		}
		//第六步发送短信和模板消息
		for (Long userId : maintainPlanAffair.getUserIds()) {
			SimpleUserVO assignUserInfo = userService.getSimpleUserInfo(userId);
			if (Func.isNotEmpty(assignUserInfo)) {
				if (Func.isNotEmpty(assignUserInfo.getOpenid())) {
					String skipUrl = "pages/home/index?footerKey=myTask&typeStatus=5";
					Map<String, String> templateDataMap = new HashMap<>(8);
					templateDataMap.put("first", "工单处理提醒");
					templateDataMap.put("thing10", "事务工单");
					templateDataMap.put("thing9", maintainPlanAffair.getPlanDesc());
					templateDataMap.put("thing18", address.length() > 16 ? address.substring(0, 15) : address);
					templateDataMap.put("thing7", userName);
					templateDataMap.put("time8", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
					templateDataMap.put("remark", "请及时登录梯无忧小程序执行事务任务!");
					templateDataMap.put("params", skipUrl);
					weChatDialogueService.sendMsg(assignUserInfo.getOpenid(), TemplateMsgConstant.AFFAIR_MESSAGE, templateDataMap);
				}
				log.info("===========给事务工单执行人发送手机短信, 手机号码:[{}]===========", assignUserInfo.getUserName(), assignUserInfo.getPhone());
			}
			Map<String, String> smsParam = new HashMap<>(2);
			smsParam.put("status", "待开始");
			SmsUtil.sendMessage(MaintenanceSmsConstant.AFFAIR_MESSAGE, BladeConstant.ADMIN_TENANT_ID, smsParam, assignUserInfo.getPhone());
		}
		return planId;
	}

	@Override
	public MaintainPlanAffairDetailVO detail(Long planId) {
		MaintainPlanAffairDetailVO maintainPlanAffairDetailVO = new MaintainPlanAffairDetailVO();
		MaintainPlanContent maintainPlanContent = maintainPlanContentService.getById(planId);
		if (maintainPlanContent == null) {
			throw new ServiceException("找不到对应的工单,请检查工单id的有效性");
		}
		PlanContentWorkDetailCommonVo planContentWorkDetailCommonVo = maintainPlanContentMapper.workDetail(planId);
		if (planContentWorkDetailCommonVo != null && planContentWorkDetailCommonVo.getBuildingType() != null) {
			planContentWorkDetailCommonVo.setBuildingTypeName(DictCache.getValue(PROJECT_TYPE_CODE, planContentWorkDetailCommonVo.getBuildingType()));
		}
		maintainPlanAffairDetailVO.setPlanContentWorkDetailCommonVo(planContentWorkDetailCommonVo);
		// 人员信息
		List<PlanMaintainUserVO> maintainUserList = maintainPlanContentUserService.selectWorkUsers(planId);
		maintainUserList = maintainUserList.stream().filter(e -> {
			Integer userSignCount = signService.count(Wrappers.<MaintainSign>lambdaQuery().eq(MaintainSign::getPlanId, e.getPlanId()).eq(MaintainSign::getUserId, e.getMaintainUserId()));
			e.setUserSignCount(userSignCount);
			if (maintainPlanContent.getStatus().equals(TaskStatusEnum.BY_FINISH.getStatus()) && maintainPlanContent.getTypeStatus().equals(MaintainPlanContentEnum.MAINTAIN_BY.getId())) {
				return userSignCount > 0;
			} else if (maintainPlanContent.getStatus().equals(TaskStatusEnum.WX_SIGN_FINISH.getStatus()) && maintainPlanContent.getTypeStatus().equals(MaintainPlanContentEnum.MAINTAIN_WX.getId())) {
				return userSignCount > 0;
			} else {
				return true;
			}
		}).collect(Collectors.toList());

		// 2023-11-21 新增是否存在过签到字段，供前端做任务转派删除规制
		for (PlanMaintainUserVO planMaintainUserVO : maintainUserList) {
			Long userId = planMaintainUserVO.getMaintainUserId();
			int isExist = signService.list(new LambdaQueryWrapper<MaintainSign>()
				.eq(MaintainSign::getPlanId, planId)
				.eq(MaintainSign::getUserId, userId)
				.eq(BaseEntity::getIsDeleted, 0)
			).size();
			if (isExist > 0) {
				planMaintainUserVO.setIsSigned(1);
			} else {
				planMaintainUserVO.setIsSigned(0);
			}
		}

		maintainPlanAffairDetailVO.setMaintainUserList(maintainUserList);
		List<MaintainMalfunctionLog> logList = malfunctionLogService.list(Wrappers.<MaintainMalfunctionLog>lambdaQuery().eq(MaintainMalfunctionLog::getPlanId, planId));
		maintainPlanAffairDetailVO.setLogList(logList);

		List<MaintainLogStatusVo> maintainLogStatusVos = malfunctionLogService.logStatusList(planId);
		for (MaintainLogStatusVo maintainLogStatusVo : maintainLogStatusVos) {
			String taskName = TaskStatusEnum.getTaskName(MaintainPlanContentEnum.MAINTAIN_AFFAIR.getId(), maintainLogStatusVo.getPlanStatus());
			maintainLogStatusVo.setPlanStatusName(taskName);
		}
		maintainPlanAffairDetailVO.setStatusVos(maintainLogStatusVos);
		List<MalFunctionHistoryVO> malFunctionHistories = malfunctionHistoryService.selectByPlanId(planId);
		maintainPlanAffairDetailVO.setMalFunctionHistories(malFunctionHistories);

		MaintainPlanAffair maintainPlanAffair = this.getOne(Wrappers.<MaintainPlanAffair>lambdaQuery().eq(MaintainPlanAffair::getPlanId, planId));
		maintainPlanAffair.setPlanDate(maintainPlanContent.getPlanDate());
		maintainPlanAffair.setCreateUserName(logList.get(0).getExecutor());
		maintainPlanAffairDetailVO.setMaintainPlanAffair(maintainPlanAffair);
		return maintainPlanAffairDetailVO;
	}

	@Override
	public IPage<AffairListVo> list(MaintainPlanAffairDTO maintainPlanAffairDTO) {
		Query query = new Query();
		query.setSize(maintainPlanAffairDTO.getSize());
		query.setCurrent(maintainPlanAffairDTO.getCurrent());
		IPage<AffairListVo> page = Condition.getPage(query);

		List<Integer> planStatuss = new ArrayList<>(10);
		//表示获取离职人员
		if (maintainPlanAffairDTO.getIsUserStatus() != null) {
			if (maintainPlanAffairDTO.getPlanStatus() == null) {
				planStatuss.add(TaskStatusEnum.SW_TO_START.getStatus());
				planStatuss.add(TaskStatusEnum.SW_UNDER_WAY.getStatus());
			} else {
				planStatuss.add(maintainPlanAffairDTO.getPlanStatus());
			}
		} else {
			if (maintainPlanAffairDTO.getPlanStatus() != null) {
				planStatuss.add(maintainPlanAffairDTO.getPlanStatus());
			}
		}
		if (planStatuss.size() > 0) {
			maintainPlanAffairDTO.setPlanStatuss(planStatuss);
		}

		List<AffairListVo> list = baseMapper.list(page, maintainPlanAffairDTO);
		page.setRecords(list);
		return page;
	}

	@Override
	public List<AffairListVo> list(MaintainPlanAffairDTO maintainPlanAffairDTO, Integer type) {

		return baseMapper.list(null, maintainPlanAffairDTO);
	}

	@Override
	public List<AffairStatusVo> getAffairStatus() {

		return baseMapper.getAffairStatus();
	}

	@Override
	public UserAffairAndCheckVo getPlanUserList(String userId) {
		UserAffairAndCheckVo userAffairAndCheckVo = new UserAffairAndCheckVo();
		MaintainPlanAffairDTO maintainPlanAffairDTO = new MaintainPlanAffairDTO();
		maintainPlanAffairDTO.setPlanUserId(userId);
		//表示离职人员
		Integer isUserStatus = 1;
		maintainPlanAffairDTO.setIsUserStatus(isUserStatus);
		List<AffairListVo> list = baseMapper.list(null, maintainPlanAffairDTO);
		List<AffairListVo> list1 = list.stream().filter(o -> o.getPlanStatus() == TaskStatusEnum.SW_TO_START.getStatus() && o.getUserNames().split(",").length == 1).collect(Collectors.toList());
		List<AffairListVo> list2 = list.stream().filter(o -> o.getPlanStatus() == TaskStatusEnum.SW_UNDER_WAY.getStatus() && o.getUserNames().split(",").length == 1).collect(Collectors.toList());
		userAffairAndCheckVo.setDisCounts(list1.size());
		userAffairAndCheckVo.setEnCounts(list2.size());
		userAffairAndCheckVo.setCounts(userAffairAndCheckVo.getDisCounts() + userAffairAndCheckVo.getEnCounts());
		return userAffairAndCheckVo;
	}

	@Override
	public List<AffairListVo> getPlanListOfUserId(String userId) {
		MaintainPlanAffairDTO maintainPlanAffairDTO = new MaintainPlanAffairDTO();
		maintainPlanAffairDTO.setPlanUserId(userId);
		List<AffairListVo> list = baseMapper.list(null, maintainPlanAffairDTO);
		return list.stream().filter(o -> (o.getPlanStatus() == TaskStatusEnum.SW_TO_START.getStatus() || o.getPlanStatus() == TaskStatusEnum.SW_UNDER_WAY.getStatus()) && o.getUserNames().split(",").length == 1).collect(Collectors.toList());
	}

}
